package captcha.service.impl;

import captcha.model.vo.CaptchaVO;
import captcha.util.StringUtils;
import captcha.model.common.Const;
import captcha.model.common.RepCodeEnum;
import captcha.model.common.ResponseModel;
import captcha.service.CaptchaCacheService;


import java.util.Objects;
import java.util.Properties;


public  abstract class AbstractLimitHandler implements FrequencyLimitHandler {
    protected   CaptchaCacheService cacheService;
    protected Properties properties;
    public final static String GET = "GET";
    public final static String LOCK = "LOCK";
    public AbstractLimitHandler(Properties properties,CaptchaCacheService cacheService) {
        this.cacheService = cacheService;
        this.properties = properties;
    }
    public String getClientCid(CaptchaVO input, String type) {
        return String.format(LIMIT_KEY ,type,input.getClientUid());
    }

}

class HolderLimitHandler extends AbstractLimitHandler {

    public final static String RECORD = "RECORD";
    public final static String BUCKET_LOCK = "BUCKET_LOCK";

    public HolderLimitHandler(Properties properties,CaptchaCacheService cacheService) {
        super(properties,cacheService);
    }

    public  ResponseModel validateGet(CaptchaVO captchaVO) {

        if(captchaVO.getClientUid() == null){
            return ResponseModel.errorMsg("clientUid is null");
        }

        String clientCid = super.getClientCid(captchaVO, RECORD);
        String bucketLock = super.getClientCid(captchaVO, BUCKET_LOCK);
        String failCount = cacheService.get(clientCid);


        if(!StringUtils.isBlank(cacheService.get(bucketLock))){
            return ResponseModel.errorMsg("请稍后再试");
        }

        if (StringUtils.isBlank(cacheService.get(clientCid))) {
            cacheService.set(clientCid,"1",60L);
            return ResponseModel.success();
        }

        cacheService.increment(clientCid,1);

        if (Long.parseLong(cacheService.get(clientCid)) > Long.parseLong(properties.getProperty(Const.REQ_GET_MINUTE_LIMIT, ONE_HUNDRED_AND_TWENTY))) {
            cacheService.set(bucketLock,LOCK,60L);
            return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LIMIT_GET_ERROR);
        }
        // 1分钟内失败5次
        if (Long.parseLong(cacheService.get(failCount)) > Long.parseLong(properties.getProperty(Const.REQ_GET_LOCK_LIMIT, FIVE))) {
            // get接口锁定5分钟
            cacheService.set(bucketLock,LOCK,Long.parseLong(properties.getProperty(Const.REQ_GET_LOCK_SECONDS, "300")));
            return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LOCK_GET_ERROR);
        }

        return null;


    }

    @Override
    public ResponseModel validateCheck(CaptchaVO captchaVO) {
        if(StringUtils.isEmpty(captchaVO.getClientUid())){
            return null;
        }
            /*String getKey = getClientCId(d, "GET");
            if(Objects.isNull(cacheService.get(getKey))){
                return ResponseModel.errorMsg(RepCodeEnum.API_REQ_INVALID);
            }*/
        String key = getClientCid(captchaVO, "CHECK");
        String v = cacheService.get(key);
        if (Objects.isNull(v)) {
            cacheService.set(key, "1", 60);
            v = "1";
        }
        cacheService.increment(key, 1);
        if (Long.parseLong(v) > Long.parseLong(properties.getProperty(Const.REQ_CHECK_MINUTE_LIMIT, SIX_HUNDRED))) {
            return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LIMIT_CHECK_ERROR);
        }
        return null;
    }

    @Override
    public ResponseModel validateVerify(CaptchaVO captchaVO) {
        if(StringUtils.isEmpty(captchaVO.getClientUid())){
            return null;
        }
            /*String getKey = getClientCId(d, "GET");
            if(Objects.isNull(cacheService.get(getKey))){
                return ResponseModel.errorMsg(RepCodeEnum.API_REQ_INVALID);
            }*/
        String key = getClientCid(captchaVO, "CHECK");
        String v = cacheService.get(key);
        if (Objects.isNull(v)) {
            cacheService.set(key, "1", 60);
            v = "1";
        }
        cacheService.increment(key, 1);
        if (Long.parseLong(v) > Long.parseLong(properties.getProperty(Const.REQ_CHECK_MINUTE_LIMIT, SIX_HUNDRED))) {
            return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LIMIT_CHECK_ERROR);
        }
        return null;
    }


}
